home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-13
/
tde3.zip
/
INT24.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-06-05
|
13KB
|
297 lines
;
; Sometimes, things may go wrong that are outside the control of an application
; program. When an application program needs to access system resources, lots
; of things can go wrong: hard disk errors, lost network connections, printing
; a file before turning on the printer, etc.... These types of errors are
; known as Critical Errors. The operating system doesn't know what to do in
; these situations, so it asks the application program for advice. Ideally,
; the application program should be prepared to handle these situations. After
; a critical error occurs in MSDOS, an application program will be asked to
; Abort, Retry, or Fail the operation.
;
; In this critical error handler (CEH), we never let the user return
; the Abort choice for the standard Abort, Retry, Fail prompt. When the
; user selects Abort, all pending work and the application program are
; terminated. Users can get very frustrated when they can't save their work
; or if they loose everything because an application can't recover from
; a critical error.
;
;------------------------ special case in 2.21 -------------------------
; A couple of days ago, I tried to edit a file on our network drive
; running Novell 3.11. The file was corrupt and there was no way to
; get out of the TDE critical error handler except by Ctrl-Alt-Del,
; AKA Vulcan nerve pinch. I added the Abort choice to the CEH to keep
; TDE out of an infinite loop. Don't returning Abort as a critical
; error leave the workstation in an unstable state or something?
; I still lose all pending work with Abort, but at least I can exit TDE.
; Shouldn't Novell recognize the Fail option in addition to Abort and Retry?
;--------------------------------- end ---------------------------------
;
; The simple critical error handler (CEH) in TDE is designed to be memory
; model independent. When we first install this CEH, pass in the FAR address
; of a CEH structure. Save the address of CEH structure in the code segment
; of our assembly CEH replacement. When a critical error occurs, load in the
; address of our CEH structure and save the return codes in the structure.
; Call the prompt functions in criterr.c, then return from interrupt.
;
; Let's set the error flag only if a Fail or Ignore condition is input by
; the user. The Ignore option is not explicity supported by this algorithm,
; but it is returned for DOS versions less than 3.0. The Fail option is
; not available for DOS versions less than 3.0. If the user selects the
; Retry option, set the ceh.flag to OK, because there is no error. By
; selecting Retry, the user just wants to retry the DOS operation, which is
; not necessarily an error condition.
;
; See:
;
; Programmer's Reference Manual, Microsoft Corporation, Redmond,
; Washington, 1986, Document No. 410630014-320-003-1285, pp. 1-20 thru
; 1-21, pp. 1-34 thru 1-38, p 1-99, pp. 1-121 thru 1-124, pp. 1-216 thru
; 1-218, pp. 2-1 thru 2-30.
;
; Ray Duncan, _Advanced MS-DOS_, Microsoft Press, Redmond, Washington,
; 1986, ISBN 0-914845-77-2, pp 89-97, pp 130-133.
;
;
; Assembler flags:
;
; QuickAssembler: qcl /c int24.asm
; MASM 6.0: ml /c /Cp /Zm int24.asm
;
; Editor name: TDE, the Thomson-Davis Editor.
; Author: Frank Davis
; Date: June 5, 1991, version 1.0
; Date: July 29, 1991, version 1.1
; Date: October 5, 1991, version 1.2
; Date: January 20, 1992, version 1.3
; Date: February 17, 1992, version 1.4
; Date: April 1, 1992, version 1.5
; Date: June 5, 1992, version 2.0
; Date: October 31, 1992, version 2.1
;
; This code is released into the public domain, Frank Davis. You may
; distribute it freely.
;typedef struct { typedef from tdestr.h
; int flag;
; int ecode;
; int rw;
; int drive;
; int extended;
; int class;
; int action;
; int locus;
; int dattr;
; char dname[10];
;} CEH;
flag EQU 0
ecode EQU 2
rw EQU 4
drive EQU 6
extended EQU 8
class EQU 10
action EQU 12
locus EQU 14
dattr EQU 16
dname EQU 18
; see any DOS tech ref manual for the format of device headers.
;
dev_attr_word EQU 4
char_dev_name EQU 10
;
; external C routine in criterr.c
;
EXTRN _crit_err_handler:FAR
_TEXT SEGMENT WORD PUBLIC 'CODE'
ASSUME cs:_TEXT, ds:NOTHING, es:NOTHING
public _install_ceh
;
; Prototype this function as far in the C header file so it may be used easily
; with any memory model. See the last section in tdefunc.h for more info.
;
_install_ceh PROC FAR
jmp initialize
ceh_pointer DW ?,? ; pointer to critical error handler structure
dos_version DW ? ; what version of DOS are we working with?
start:
;
; the first thing we need to do is turn interrupts back on. interrupts
; are disabled when the handler receives control.
;
; segment register strategy:
; use ds to access variables in the code segment and the device header
; use es to access the ceh structure.
;
sti ; turn interrupts back on
push bx ; push required registers
push cx
push dx
push ds
push es
ASSUME ds:_TEXT, es:NOTHING ; put cs in ds and tell assembler
; ds references code, _TEXT seg
mov dx, cs
mov ds, dx
mov dx, di ; put error code in dx
xor dh, dh ; high part of di is undef'ed
mov bx, WORD PTR ceh_pointer+2 ; get SEGMENT of ceh struc
mov es, bx ; put it in es
mov di, WORD PTR ceh_pointer ; get OFFSET of ceh struc
mov WORD PTR es:[di].ecode, dx ; save error code
mov dl, ah ; move error stuff to dl
and dl, 1 ; 1 == write error
mov WORD PTR es:[di].rw, dx ; save read/write error code
mov dl, al ; put drive letter in dl
mov WORD PTR es:[di].drive, dx ; save drive number
test ah, 80h ; was this a character or block dev
jz drive_err ; if fail, then block error
mov ds, bp ; put SEGMENT of device header in ds
mov dx, WORD PTR [si].dev_attr_word ; see DOS tech ref, get dev attr
test dx, 8000h ; was there a prob w/ FAT
jz drive_err ; if bit 15 == 0, drive error - FAT prob
mov WORD PTR es:[di].dattr, 1 ; 1 == character device
mov bx, di ; save OFFSET of CEH struct in bx
add di, dname ; load destination of char dev name
add si, char_dev_name ; char dev
mov cx, 8 ; char name is 8 bytes
rep movsb ; move 8 bytes of driver name
xor al, al ; zero out al
stosb ; store a terminating NULL
mov di, bx ; get back the OFFSET of CEH struct
jmp SHORT get_extended_error
ALIGN 2
drive_err:
mov WORD PTR es:[di].dattr, 0 ; 0 == disk drive
get_extended_error:
mov dx, cs ; put cs back into ds
mov ds, dx
mov ax, WORD PTR ds:dos_version ; get DOS version
or ax, ax ; is it 0?
jz no_ext_avail ; skip extended error
;
; page 1-216, Programmer's Ref Man, 1986, function 59h pretty much wipes
; out all registers that don't return info. function 59h is available
; for DOS >= 3.
;
push di
push ds
push es
xor bx, bx ; version indicator, 0 = current
mov ah, 59h ; function 59h == get extended err
int 21h ; Standard DOS interrupt
pop es
pop ds
pop di
cmp ax, 88 ; check for return code > 88
ja no_ext_avail ; if ax <= 88, we have info
mov WORD PTR es:[di].extended, ax ; save ext err code
xor ax, ax ; zero out ax
mov al, bh ; get error class
mov WORD PTR es:[di].class, ax ; save error class
mov al, bl ; get suggested action
mov WORD PTR es:[di].action, ax ; save suggested action
mov al, ch ; get locus
mov WORD PTR es:[di].locus, ax ; save locus
jmp SHORT prompt_user ; now, ask user what to do
ALIGN 2
no_ext_avail:
xor ax, ax ; zero out ax
mov WORD PTR es:[di].extended, ax ; not avail
mov WORD PTR es:[di].class, ax ; not avail
mov WORD PTR es:[di].action, ax ; not avail
mov WORD PTR es:[di].locus, ax ; not avail
prompt_user:
push di ; save OFFSET of CEH struct
push es ; save SEGMENT OF CEH struct
push ds ; save code segment in ds
mov ax, ss ; put stack segment in ds
mov ds, ax ; C routine expects stack seg in ds
call FAR PTR _crit_err_handler ; return code is in ax
pop ds ; get back our registers
pop es
pop di
mov bx, WORD PTR ds:dos_version ; get the DOS version
or bx, bx ; is bx == 0?
jne retry_or_fail ; DOS version is >= 3
cmp ax, 3 ; did user try fail?
jne retry_or_fail ; cannot fail with DOS < 3
mov ax, 0 ; change it to Ignore
ALIGN 2
retry_or_fail:
mov dx, -1 ; if we fail, store a -1
cmp ax, 1 ; did user do a retry?
jne end_int_24 ; if retry, change error code
xor dx, dx ; reset error flag on retry
end_int_24:
mov WORD PTR es:[di].flag, dx ; save ceh flag
pop es
pop ds
pop dx
pop cx
pop bx ; pop registers
iret ; return from interrupt
; ***********************************************************************
; prototype for _install_ceh in the C header file, tdefunc.h, is
;
; void far install_ceh( void far * )
;
; The formal parameters are available on the stack. Use bp register to
; access them.
;
; ***********************************************************************
initialize:
push bp ; setup bp to access formal parameter
mov bp, sp
push ds ; save ds
ASSUME ds:_TEXT ; tell assembler ds references code, _TEXT seg
mov ax, cs
mov ds, ax ; put cs in ds - required by function 25h, below
mov ah, 30h ; function 30h == get DOS version
int 21h ; DOS interrupt
xor bx, bx ; start out with zero for DOS version
cmp al, 3 ; compare major version
jl store_dos ; if less than version 3, store 0
mov bx, 3 ; else store 3 for DOS >= 3
store_dos:
mov WORD PTR dos_version, bx ; save DOS info for my int 24
mov ax, WORD PTR [bp+6] ; load OFFSET of void FAR *
mov WORD PTR ceh_pointer, ax ; save OFFSET of void FAR *
mov ax, WORD PTR [bp+8] ; load SEGMENT of void FAR *
mov WORD PTR ceh_pointer+2, ax ; save SEGMENT of void FAR *
mov dx, OFFSET start ; get new offset of int 24
; we have already set ds above
mov ax, 2524h ; use function 25 so int 24 points
int 21h ; to my critical error routine
pop ds ; clean up
pop bp
retf
_install_ceh endp
_TEXT ends
end